#ifndef XLCOMM_NET_HTTPRESPONSE_H_
#define XLCOMM_NET_HTTPRESPONSE_H_

#include <map>
#include <string>

#include "xlcomm/copyable.h"

namespace xlcomm {
namespace net {

class HttpResponse : copyable {
 public:
  enum StatusCode {
    kUnknown,
    k200Ok = 200,
    k301MovedPermanently = 301,
    k400BadRequest = 400,
    k404NotFound = 404,
  };

  HttpResponse() : close_connection_(true) {}

  std::string StatusCodeAndMessage(StatusCode code) const {
    switch (code) {
      case kUnknown:
        return "0 Unknown";
      case k200Ok:
        return "200 OK";
      case k301MovedPermanently:
        return "301 Moved Permanently";
      case k400BadRequest:
        return "400 Bad Request";
      case k404NotFound:
        return "404 Not Found";
    }
    return "0 Unknown";
  }

  std::string ToString() {
    std::string status_line =
        kVersion + " " + StatusCodeAndMessage(status_code_);

    if (close_connection_) {
      AddHeader("Connection", "close");
    } else {
      AddHeader("Connection", "Keep-Alive");
      AddHeader("Content-Length", std::to_string(body_.length()));
    }
    std::string head_lines;
    std::map<std::string, std::string>::const_iterator it;
    for (it = headers_.begin(); it != headers_.end(); ++it) {
      head_lines += it->first;
      head_lines += ": ";
      head_lines += it->second;
      head_lines += kCrLf;
    }

    std::string resp = status_line + kCrLf + head_lines + kCrLf + body_;
    LOG_DEBUG << "response--------\n" << resp;
    return resp;
  }

  void Reset() {
    status_code_ = kUnknown;
    headers_.clear();
    body_.clear();
  }

  void set_close_connection(bool close) { close_connection_ = close; }
  void set_status_code(StatusCode code) { status_code_ = code; }
  void AddHeader(const std::string& key, const std::string& value) {
    headers_[key] = value;
  }
  void set_body(const std::string& body) { body_ = body; }

 private:
  const std::string kCrLf = "\r\n";
  const std::string kVersion = "HTTP/1.1";

  bool close_connection_;
  StatusCode status_code_;
  std::map<std::string, std::string> headers_;
  std::string body_;
};

}  // namespace net
}  // namespace xlcomm

#endif  // XLCOMM_NET_HTTPRESPONSE_H_